package com.dana.friend.service.exam.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.core.constants.Constants;
import com.core.domain.TableDataInfo;
import com.core.utils.ThreadLocalUtils;
import com.dana.friend.domain.exam.dto.QueryExamDTO;
import com.dana.friend.domain.exam.vo.ExamVO;
import com.dana.friend.manager.ExamCacheManager;
import com.dana.friend.mapper.exam.ExamMapper;
import com.dana.friend.service.exam.IExamService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class ExamServiceImpl implements IExamService {

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ExamCacheManager examCacheManager;

    /**
     * 查询列表,从数据库中获取
     *
     * @param queryExamDTO 参数
     */
    @Override
    public List<ExamVO> getList(QueryExamDTO queryExamDTO) {
        //mybatis自动分页
        PageHelper.startPage(queryExamDTO.getPageNum(), queryExamDTO.getPageSize());
        return examMapper.selectExamList(queryExamDTO);
    }


    /**
     * 从redis中获取竞赛列表
     * @param queryExamDTO
     */

    @Override
    public TableDataInfo getRedisList(QueryExamDTO queryExamDTO) {
        //第一次发布竞赛之后,redis中只有刚才发布的竞赛的信息,以前存储的已经发布的竞赛信息不会在redis中缓存
        //解决办法:去数据库中刷新缓存,将数据库中发布的竞赛信息也缓存到redis中
         Long total = examCacheManager.getListSize(queryExamDTO.getType(),null);
         List<ExamVO> examList;
        if (total == null || total <= 0) {
            //先去数据库查询,并且更新缓存
            examList=getList(queryExamDTO);
            //更新缓存
            examCacheManager.refreshCache(queryExamDTO.getType(),null);
            total= new PageInfo<>(examList).getTotal();
        }else {
            examList=examCacheManager.getExamVOList(queryExamDTO,null);
            total=examCacheManager.getListSize(queryExamDTO.getType(),null);
        }
        if (CollectionUtil.isEmpty(examList)){
            return TableDataInfo.empty();
        }
        assembleExamVoList(examList);
        return TableDataInfo.success(examList,total);
    }

    /**
     * 获取竞赛中第一个题目
     * @param examId
     * @return
     */
    @Override
    public String getFirstQuestion(Long examId) {
        acquireTotalAndRefresh(examId);
        return examCacheManager.getFirstQuestion(examId).toString();
    }

    /**
     * 获取竞赛中上一个题目
     * @param questionId
     * @param examId
     * @return
     */
    @Override
    public String preQuestion(Long questionId, Long examId) {
        acquireTotalAndRefresh(examId);
        return examCacheManager.preQuestion(questionId,examId).toString();
    }
    /**
     * 获取竞赛中下一个题目
     * @param questionId
     * @param examId
     * @return
     */
    @Override
    public String nextQuestion(Long questionId, Long examId) {
        acquireTotalAndRefresh(examId);
        return examCacheManager.nextQuestion(questionId,examId).toString();
    }

    /**
     * 获取当前用户报名了哪些竞赛
     * 如果用户报名的竞赛在竞赛列表中存在,那么setEnter设置为true,前端根据setEnter就会将竞赛列表转换成已经报名
     *
     * @param examList
     */
    private void assembleExamVoList(List<ExamVO> examList) {
        //获取当前用户
        Long userId = ThreadLocalUtils.get(Constants.USER_ID, Long.class);
        //判断竞赛列表中对于当前用户报名了哪些竞赛
        List<Long> examIdList = examCacheManager.getAllUserExamList(userId);
        if (CollectionUtil.isEmpty(examIdList)) {
            return;
        }

        for (ExamVO examVO : examList) {
            if (examIdList.contains(examVO.getExamId())) {
                examVO.setEnter(true);
            }
        }
    }

    /**
     * 判定缓存是否有数据,如果没有就刷新缓存
     * @param examId
     */
    private void acquireTotalAndRefresh(Long examId){
        Long examQuestionListSize = examCacheManager.getExamQuestionListSize(examId);
        if (examQuestionListSize == null || examQuestionListSize <= 0) {
            //查询数据库刷新缓存
            examCacheManager.refreshExamQuestion(examId);
        }
    }
}
